package au.com.acpfg.xml.query; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.knime.core.data.DataCell; import org.knime.core.data.DataType; import au.com.acpfg.xml.query.XMLQueryEntry.ResultsType; /** * Class which is used to traverse each raw XQuery output to extract the type of * results desired by the user. A similar interface to <code>class java.lang.StringBuffer</code> * but there is no requirement that the traversal do anything with strings * * @author andrew.cassin * */ public class XQueryReporter { /** * XQuery result callbacks must respond to some/all of these as required * @author andrew.cassin * */ public enum QueryResponseFragmentType { RESP_STRING, RESP_INT, RESP_START_ELEMENT, // <element RESP_END_ELEMENT_TAG, // </element> RESP_END_TAG, // > RESP_ATTRIBUTE, // key=value RESP_INCOMPLETE_END_ELEMENT // /> }; private final int MAX_QLEN = 10; // maximum length of callback vectors /* lists of callbacks, one array per QueryResponseFragmentType -- speed is important here! */ private XQueryResponseInterface[] m_cb_string; private XQueryResponseInterface[] m_cb_int; private XQueryResponseInterface[] m_cb_element_start; private XQueryResponseInterface[] m_cb_element_end; private XQueryResponseInterface[] m_cb_end_tag; private XQueryResponseInterface[] m_cb_attribute; private XQueryResponseInterface[] m_cb_incomplete_end_tag; private final List<XQueryReporterInterface> m_reporters = new ArrayList<XQueryReporterInterface>(); private final HashMap<String,XQueryReporterInterface> m_report_map = new HashMap<String,XQueryReporterInterface>(); public XQueryReporter() { m_cb_string = new XQueryResponseInterface[MAX_QLEN]; m_cb_int = new XQueryResponseInterface[MAX_QLEN]; m_cb_element_start = new XQueryResponseInterface[MAX_QLEN]; m_cb_element_end = new XQueryResponseInterface[MAX_QLEN]; m_cb_end_tag = new XQueryResponseInterface[MAX_QLEN]; m_cb_attribute = new XQueryResponseInterface[MAX_QLEN]; m_cb_incomplete_end_tag = new XQueryResponseInterface[MAX_QLEN]; for (int i=0; i<MAX_QLEN; i++) { m_cb_string[i] = null; m_cb_int[i] = null; m_cb_element_start[i] = null; m_cb_element_end[i] = null; m_cb_end_tag[i]= null; m_cb_attribute[i] = null; m_cb_incomplete_end_tag[i] = null; } } public void call(QueryResponseFragmentType type, String attrName, String attrVal) { call(type, attrName+"=\""+attrVal+"\""); } public void call(QueryResponseFragmentType type, Integer val) { call(type, val.toString()); } public void call(String val) { call(QueryResponseFragmentType.RESP_STRING, val); } public void call(QueryResponseFragmentType type, String val) { XQueryResponseInterface[] vec = null; switch (type) { case RESP_STRING: vec = m_cb_string; break; case RESP_INT: vec = m_cb_int; break; case RESP_START_ELEMENT: vec = m_cb_element_start; break; case RESP_END_ELEMENT_TAG: vec = m_cb_element_end; break; case RESP_END_TAG: vec = m_cb_end_tag; break; case RESP_ATTRIBUTE: vec = m_cb_attribute; break; case RESP_INCOMPLETE_END_ELEMENT: vec = m_cb_incomplete_end_tag; break; } if (vec != null) { for (int i=0; i<vec.length; i++) { if (vec[i] != null) { vec[i].callback(type, val); } else { // vec[i] == null so that means the callbacks for this type have finished... so return; } } } } public void register_reporter(XQueryReporterInterface xqri, String colname) throws Exception { m_reporters.add(xqri); if (m_report_map.containsKey(colname)) { throw new Exception("Only one reporter can report a given cell -- programmer error!"); } m_report_map.put(colname, xqri); } public void reset() { for (XQueryReporterInterface r : m_reporters) { r.reset(); } } public DataCell getResultCell(String colname) { if (m_report_map.containsKey(colname)) return m_report_map.get(colname).getCell(colname); return DataType.getMissingCell(); } public void register_callback(QueryResponseFragmentType type, XQueryResponseInterface xqrc) throws Exception { switch (type) { case RESP_STRING: add(xqrc, m_cb_string); break; case RESP_INT: add(xqrc, m_cb_int); break; case RESP_START_ELEMENT: add(xqrc, m_cb_element_start); break; case RESP_END_ELEMENT_TAG: add(xqrc, m_cb_element_end); break; case RESP_END_TAG: add(xqrc, m_cb_end_tag); break; case RESP_ATTRIBUTE: add(xqrc, m_cb_attribute); break; case RESP_INCOMPLETE_END_ELEMENT: add(xqrc, m_cb_incomplete_end_tag); break; default: throw new Exception("Unknown response type: "+type); } } private void add(XQueryResponseInterface xqrc, XQueryResponseInterface[] vec) throws Exception { for (int i=0; i<MAX_QLEN; i++) { if (vec[i] == null) { vec[i] = xqrc; return; } } throw new Exception("XQueryReporter::add() vector full, increase MAX_QLEN!"); } }